/** @format */

import {
    Camera,
    director,
    Layers,
    Material,
    Node,
    RenderTexture,
    size,
    Sprite,
    SpriteComponent,
    SpriteFrame,
    UITransform,
    v3,
    view,
    View,
} from "cc";
import { app } from "../App";
import { IBaseInterface } from "../Interface/BaseInterface";
import { SingleBase } from "../Interface/SingleBase";
import { PostEffectBase } from "../Module/PostEffect/PostEffectBase";
import { PostEffectGrap } from "../Module/PostEffect/PostEffectGrap";
import { PostEffectResult } from "../Module/PostEffect/PostEffectResult";

/**
 * 屏幕后处理管理类
 */
export class PostEffectManager extends SingleBase implements IBaseInterface {
    private _peCameraNode: Node = null;
    private _peSprtieNode: Node = null;
    public rt: RenderTexture = null;
    private _timerId: number = -1;
    public nodeMainCamera: Node = null;

    public peList: PostEffectBase[] = [];

    public currPe: PostEffectBase = null;

    public index = 3;

    public static get instance(): PostEffectManager {
        return this._instance ? (this._instance as PostEffectManager) : (this._instance = new PostEffectManager());
    }

    public init(): void {
        super.init();
    }

    private resetCameraByOther(): void {
        this._peCameraNode = director.getScene().getChildByName("Main Camera");

        let winSize = view.getVisibleSize();
        const rt = new RenderTexture();
        rt.reset({
            width: winSize.width,
            height: winSize.height,
        });
        this.rt = rt;
        this._peCameraNode.getComponent(Camera).targetTexture = rt;
    }

    /**
     * 开启后处理
     */
    public open(): void {
        this.resetCameraByOther();
        this._refresh();
    }

    /**
     * 设置材质
     * @param mtl 材质
     */
    public setMaterial(mtl: Material): void {
        this._peSprtieNode.getComponent(Sprite).setMaterialInstance(mtl, 0);
    }

    /**
     * 关闭后处理
     */
    public close(): void {
        if (this._timerId > -1) {
            app.timerMgr.unschedule(this._timerId);
            this._timerId = -1;
        }
        if (this._peSprtieNode) this._peSprtieNode.destroy();
        this._peSprtieNode = null;
        this.nodeMainCamera = null;
        this._peCameraNode = null;
        this.peList.forEach((pe) => {
            pe.unloadPass();
        });
        this.peList = [];
        this.index = 3;
        director.getScene().getChildByName("Main Camera").getComponent(Camera).targetTexture = null;
    }

    private _refresh(): void {
        for (let i = 0, len = this.peList.length; i < len; i++) {
            let pe = this.peList[i];
            pe.loadPass();
        }
    }

    /**
     * 实时同步主摄像机状态
     * @param dt
     * @returns
     */
    private onUpdate(dt: number): void {
        if (!this.nodeMainCamera) {
            return;
        }
        this._peCameraNode.setPosition(this.nodeMainCamera.getPosition());
        this._peCameraNode.eulerAngles = this.nodeMainCamera.eulerAngles;
        for (let i = 0, len = this.peList.length; i < len; i++) {
            let pe = this.peList[i];
            pe.onUpdate();
        }
    }

    public get peSprite(): Sprite {
        return this._peSprtieNode?.getComponent(Sprite);
    }

    /**
     * 最终pass
     */
    public finalPass(): void {
        let winSize = view.getVisibleSize();
        this._peSprtieNode = new Node("后处理最终渲染节点");
        this._peSprtieNode.layer = Layers.Enum.UI_2D;
        app.sceneMgr.getCurrCanvasNode().addChild(this._peSprtieNode);
        this._peSprtieNode.setSiblingIndex(0);
        let sp: Sprite = this._peSprtieNode.addComponent(Sprite);

        let transform = this._peSprtieNode.getComponent(UITransform);
        transform.width = winSize.width;
        transform.height = winSize.height;

        let sf = new SpriteFrame();
        sf.texture = this.peList[this.peList.length - 1].getRt();
        sp.spriteFrame = sf;
    }

    release(): void {
        super.release();
    }
}
